﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Demo
{
    class Server
    {
        class ClientInfo
        {
            public Socket socket;
            public byte[] bytes = new byte[1024];
        }

        List<ClientInfo> socketClients = new List<ClientInfo>();

        public Server()
        {
            InitServer();
        }

        public void InitServer()
        {
            Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //服务端需绑定监听的IP和端口号
            string ip = "127.0.0.1";
            int port = 8888;
            IPAddress iPAddress = IPAddress.Parse(ip);
            IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, port);

            socketServer.Bind(iPEndPoint);
            socketServer.Listen(0);
            Console.WriteLine("服务器异步启动成功");

            socketServer.BeginAccept(AcceptCallBack, socketServer);
        }

        private void AcceptCallBack(IAsyncResult ar)
        {
            try
            {
                Socket socketServer = (Socket)ar.AsyncState;
                Socket socketClient = socketServer.EndAccept(ar);

                ClientInfo clientInfo = new ClientInfo();
                clientInfo.socket = socketClient;
                socketClients.Add(clientInfo);  //连接后将Socket添加到列表

                Msg msg = new Msg();
                msg.Command = "Connected";
                msg.Client = FormatAddress(socketClient);
                msg.Value = FormatClients();
                string json = JsonConvert.SerializeObject(msg);
                SendAsync(socketClient,json);
                //ShowClientInfo(socketClient);
                //string ip = FormatAddress(socketClient);
                Console.WriteLine("客户端异步连接服务端成功");

                //继续等待接收客户端连接

                socketClient.BeginReceive(clientInfo.bytes, 0, 1024, 0, ReceiveCallback, clientInfo);
                socketServer.BeginAccept(AcceptCallBack, socketServer);
            }
            catch (SocketException se)
            {
                Console.WriteLine(se.Message);
                throw;
            }
        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                ClientInfo clientInfo = (ClientInfo)ar.AsyncState;
                int count = clientInfo.socket.EndReceive(ar);
                if (count <= 0)
                {
                    string ip = FormatAddress(clientInfo.socket); //线程安全    对象的调用  变量的值
                    //删除List里的用户信息
                    socketClients.Remove(clientInfo);                                   //这俩句
                    clientInfo.socket.Close();

                    //通知其他客户端某客户端已下线
                    Console.WriteLine("客户端关闭连接");
                    return;
                }
                string str = Encoding.UTF8.GetString(clientInfo.bytes, 0, count);

                //str = "xxxx";
                //str = "127.0.0.1:84651|xxxx";
                string clientIP = FormatAddress(clientInfo.socket);
                Msg msg = JsonConvert.DeserializeObject<Msg>(str);
                msg.Client = clientIP;
                Console.WriteLine("服务器接收到的异步信息是：" + msg.ToString());

                string sendStr = JsonConvert.SerializeObject(msg);//FormatAddress(clientInfo.socket) + "|" + str;


                //每次发送是对应socket-client，且每个客户端有自己的socket
                //对于服务端来说，应保存所有已连接客户端的socket
                for (int i = 0; i < socketClients.Count; i++)
                {
                    SendAsync(socketClients[i].socket, sendStr);
                }
                //继续接收信息

                clientInfo.socket.BeginReceive(clientInfo.bytes, 0, 1024, 0, ReceiveCallback, clientInfo);
            }

            catch (SocketException se)
            {
                Console.WriteLine(se.Message);

            }
        }

        public void SendAsync(Socket socketClient, string value)
        {
            byte[] sendbytes = Encoding.UTF8.GetBytes(value);//把字符串转化为byte
            socketClient.BeginSend(sendbytes, 0, sendbytes.Length, 0, SendCallBack, socketClient);
        }

        private void SendCallBack(IAsyncResult ar)
        {
            try
            {
                Socket socketClient = (Socket)ar.AsyncState;
                int count = socketClient.EndReceive(ar);
                Console.WriteLine("信息发送成功，长度为：" + count);
            }

            catch (SocketException se)
            {
                Console.WriteLine(se.Message);
            }

        }
       

        private string FormatAddress(Socket socket)
        {
            string clientIP = ((IPEndPoint)socket.RemoteEndPoint).Address.ToString();
            string clientPort = ((IPEndPoint)socket.RemoteEndPoint).Port.ToString();
            return string.Format("{0}:{1}", clientIP, clientPort);
        }
        //IP:PORT|IP:PORT|IP:PORT
        private string FormatClients()
        {
            string ips = "";
            foreach (var item in socketClients)
            {
                string ip = FormatAddress(item.socket);
                ips += ip + "|";
            }
            if (!string.IsNullOrEmpty(ips))
            {
                ips = ips.Substring(0, ips.Length - 1);
            }
            return ips;
        }
    }
}
